package cn.openea.perpartner.cms.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.openea.perpartner.cms.factory.UserContext;
import cn.openea.perpartner.cms.web.dto.AssignDto;
import cn.openea.perpartner.cms.web.dto.CommunityDto;
import cn.openea.perpartner.cms.web.dto.CommunityLogDto;
import cn.openea.perpartner.cms.web.dto.RandomDto;
import cn.openea.perpartner.cms.web.entity.CmsCommunity;
import cn.openea.perpartner.cms.web.mapper.CmsCommunityLogMapper;
import cn.openea.perpartner.cms.web.mapper.CmsCommunityMapper;
import cn.openea.perpartner.cms.web.service.ICmsCommunityService;
import cn.openea.perpartner.cms.web.service.ICmsFavoritesService;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.openea.perpartner.cms.web.entity.CmsCommunityLog;
import cn.openea.perpartner.common.core.exception.ServiceException;
import cn.openea.perpartner.common.core.utils.StringUtils;
import cn.openea.perpartner.system.util.ToolsUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


/**
 * (CmsCommunity)表服务实现类
 *
 * @author makejava
 * @since 2022-08-10 14:30:24
 */
@Service("cmsCommunityService")
public class CmsCommunityServiceImpl extends ServiceImpl<CmsCommunityMapper, CmsCommunity> implements ICmsCommunityService {

    @Autowired
    private CmsCommunityLogMapper communityLogMapper;
    @Autowired
    private ICmsFavoritesService favorityService;

    @Override
    public List<CmsCommunity> selectList(String userId, String searchStr) {
        LambdaQueryWrapper<CmsCommunity> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(userId)) {
            wrapper.and(wrap -> wrap.eq(CmsCommunity::getCreateUser, userId)
                    .or().eq(CmsCommunity::getUpdateUser, userId)
            );
        }
        if (StrUtil.isNotBlank(searchStr)) {
            if (StringUtils.isNumeric(searchStr)) {
                Date date = DateUtil.offsetDay(DateUtil.date(), -Integer.parseInt(searchStr));
                String dateTime = DateUtil.formatDate(date);
                wrapper.like(CmsCommunity::getUpdateTime, dateTime);
            } else {
                wrapper.and(wrap -> wrap.like(CmsCommunity::getOpeneaId, searchStr)
                        .or().like(CmsCommunity::getUserName, searchStr)
                        .or().like(CmsCommunity::getUpdateUser, searchStr)
                        .or().like(CmsCommunity::getNickName, searchStr)
                        .or().like(CmsCommunity::getCooperateGrade, searchStr)
                        .or().like(CmsCommunity::getPhoneNum, searchStr)
                        .or().like(CmsCommunity::getArea, searchStr)
                        .or().like(CmsCommunity::getAddress, searchStr)
                        .or().like(CmsCommunity::getCategory, searchStr)
                );
            }
        }
        wrapper.orderByAsc(CmsCommunity::getUpdateTime);
        wrapper.orderByDesc(CmsCommunity::getCooperateGrade);
        wrapper.orderByDesc(CmsCommunity::getOpeneaId);
        List<CmsCommunity> communityList = list(wrapper);
        for (CmsCommunity community : communityList) {
            long dateBetween = DateUtil.between(DateUtil.parseDate(community.getUpdateTime()), DateUtil.date(), DateUnit.DAY);
            community.setDateBetween(dateBetween);
        }
        return communityList;
    }

    @Override
    public String importData(List<CmsCommunity> communityList) {
        if (StringUtils.isNull(communityList) || communityList.isEmpty()) {
            throw new ServiceException("导入客户数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (CmsCommunity community : communityList) {
            try {
                Map<String, Object> columMap = BeanUtil.beanToMap(community);
                columMap.remove("unid");
                //若此条记录内容全部为空，则跳过不导入
                boolean hasNullColumn = true;
                for (Map.Entry<String, Object> entry : columMap.entrySet()) {
                    if (StrUtil.isNotEmpty((String) entry.getValue())) {
                        hasNullColumn = false;
                        break;
                    }
                }
                if (hasNullColumn) {
                    continue;
                }
                community.setOpeneaId(ToolsUtil.autoUserID());
                community.setCreateUser(UserContext.getUserId());
                community.setUpdateUser(UserContext.getUserId());
                community.setNickName(UserContext.getUserName());
                baseMapper.insert(community);
                successNum++;
                successMsg.append("<br/>").append(successNum).append("、客户 ").append(community.getUserName()).append(" 导入成功");
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、客户 " + community.getUserName() + " 导入失败：";
                failureMsg.append(msg).append(e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    @Override
    public String randomImportData(List<RandomDto> randomDtoList) {
        if (StringUtils.isNull(randomDtoList) || randomDtoList.isEmpty()) {
            throw new ServiceException("导入客户数据不能为空！");
        }
        //打乱顺序
        Collections.shuffle(randomDtoList);
        List<CmsCommunity> communityList = new ArrayList<>();
        String[] categoryArray = {"母婴用品", "家用消费品", "美妆", "宠物", "健康", "健身", "3c产品", "学生用品"};
        String msg = "导入成功！";
        try {
            for (RandomDto randomDto : randomDtoList) {
                Map<String, Object> columMap = BeanUtil.beanToMap(randomDto);
                columMap.remove("unid");
                //若此条记录内容全部为空，则跳过不导入
                boolean hasNullColumn = true;
                for (Map.Entry<String, Object> entry : columMap.entrySet()) {
                    if (StrUtil.isNotEmpty((String) entry.getValue())) {
                        hasNullColumn = false;
                        break;
                    }
                }
                if (hasNullColumn) {
                    continue;
                }
                CmsCommunity community = new CmsCommunity();
                BeanUtil.copyProperties(randomDto, community);
                community.setOpeneaId(ToolsUtil.autoUserID(" 2021-01-01", "2022-08-09", 3));
                community.setCreateUser(UserContext.getUserId());
                //随机替换品类
                Random random = new Random();
                List<String> categoryList = Arrays.asList(categoryArray);
                int index = random.nextInt(categoryList.size());
                community.setCategory(categoryList.get(index));
                community.setCooperateGrade("一般");
                if ("钻石".equals(randomDto.getCooperateGrade())) {
                    community.setCooperateGrade("高级");
                }
                if ("白金|白银".contains(randomDto.getCooperateGrade())) {
                    community.setCooperateGrade("中级");
                }
                communityList.add(community);
            }
            saveBatch(communityList);
        } catch (Exception e) {
            msg = "导入失败！";
            log.error(msg, e);
        }
        return msg;
    }

    @Override
    public CommunityDto queryById(Long id) {
        CmsCommunity community = baseMapper.selectById(id);
        CommunityDto communityDto = new CommunityDto();
        communityDto.setCommunity(community);
        //获取跟踪记录数据
        LambdaQueryWrapper<CmsCommunityLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CmsCommunityLog::getCommunityId, id);
        wrapper.eq(CmsCommunityLog::getUserid, UserContext.getUserId());
        List<CmsCommunityLog> communityLogList = communityLogMapper.selectList(wrapper);

        List<CommunityLogDto> communityLogDtoList = new ArrayList<>();
        for (CmsCommunityLog communityLog : communityLogList) {
            CommunityLogDto communityLogDto = new CommunityLogDto();
            communityLogDto.setCommunityLogId(communityLog.getUnid());
            communityLogDto.setContent(communityLog.getContent());
            communityLogDto.setCreateTime(communityLog.getCreateTime());
            String createDate = DateUtil.parseDate(communityLog.getCreateTime()).toDateStr();
            String nowDate = DateUtil.today();
            //判断记录是否当天创建的，当天记录是可以编辑的
            communityLogDto.setEdit(nowDate.equals(createDate));
            communityLogDtoList.add(communityLogDto);
        }
        communityDto.setLogData(communityLogDtoList);
        return communityDto;
    }

    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    @Override
    public boolean save(CommunityDto dto) {
        //将前端customerDto数据对象转为为customer对象，取客户基础数据
        boolean isSuccess;
        CmsCommunity community = dto.getCommunity();
        String openeaId = community.getOpeneaId();
        if (StrUtil.isBlank(openeaId)) {
            openeaId = ToolsUtil.autoUserID();
            community.setOpeneaId(openeaId);
        }
        if (ObjectUtil.isEmpty(community.getUnid())) {
            community.setCreateUser(UserContext.getUserId());
            community.setUpdateUser(UserContext.getUserId());
            community.setNickName(UserContext.getUserName());
            community.setUnid(IdUtil.getSnowflake(1, 1).nextId());
        }
        //更新基础数据
        isSuccess = saveOrUpdate(community);
        //从customerDto对象取任务跟踪记录数据
        List<CommunityLogDto> communityLogDtoList = dto.getLogData();
        List<Long> logIdList = new ArrayList<>();
        for (CommunityLogDto communityLogDto : communityLogDtoList) {
            logIdList.add(communityLogDto.getCommunityLogId());
        }
        if (logIdList.isEmpty()){
            return isSuccess;
        }
        LambdaQueryWrapper<CmsCommunityLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(CmsCommunityLog::getUnid, logIdList);
        wrapper.eq(CmsCommunityLog::getUserid, community.getUpdateUser());
        List<CmsCommunityLog> customerLogList = communityLogMapper.selectList(wrapper);
        //insert,第一次跟踪记录
        int len = communityLogDtoList.size() - 1;
        CommunityLogDto customerLogDto = communityLogDtoList.get(len);
        if (customerLogList.isEmpty()) {
            CmsCommunityLog communityLog = new CmsCommunityLog();
            communityLog.setUserid(UserContext.getUserId());
            communityLog.setCommunityId(community.getUnid());
            communityLog.setContent(customerLogDto.getContent());
            return communityLogMapper.insert(communityLog) > 0;
        }
        //insert n+1次跟踪记录
        if (logIdList.size() > customerLogList.size()) {
            CmsCommunityLog communityLog = new CmsCommunityLog();
            communityLog.setUserid(UserContext.getUserId());
            communityLog.setCommunityId(community.getUnid());
            communityLog.setContent(customerLogDto.getContent());
            isSuccess = communityLogMapper.insert(communityLog) > 0;
        }
        //update
        for (int i = 0; i < customerLogList.size(); i++) {
            customerLogDto = communityLogDtoList.get(i);
            //跟踪记录不变，则不进行数据更新
            if (customerLogList.get(i).getContent().equals(customerLogDto.getContent())) {
                continue;
            }
            customerLogList.get(i).setContent(customerLogDto.getContent());
            isSuccess = communityLogMapper.updateById(customerLogList.get(i)) > 0;
        }
        return isSuccess;
    }

    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    @Override
    public boolean recycle(List<Long> idList) {
        //回收前，同时删除销售的收藏记录
        LambdaUpdateWrapper<CmsCommunity> wrapper = new LambdaUpdateWrapper<>();
        List<CmsCommunity> communityList = list(wrapper);
        communityList.forEach(community -> favorityService.deleteByLinkId(community.getUnid(), community.getUpdateUser()));

        wrapper.in(CmsCommunity::getUnid, idList)
                .set(CmsCommunity::getUpdateUser, "")
                .set(CmsCommunity::getNickName, "");
        return baseMapper.update(null, wrapper) > 0;
    }

    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    @Override
    public boolean assign(List<AssignDto> assignList) {
        boolean isSuccess = false;
        for (AssignDto dto : assignList) {
            CmsCommunity community = baseMapper.selectById(dto.getAssignId());
            community.setUpdateUser(dto.getUserId());
            community.setNickName(dto.getUserName());
            isSuccess = baseMapper.updateById(community) > 0;
        }
        return isSuccess;
    }

    @Override
    public List<Object> selectLogList(int offset) {
        //获取当前时间
        DateTime dateTime = DateUtil.offsetWeek(new DateTime(), offset);
        LambdaUpdateWrapper<CmsCommunityLog> wrapper = new LambdaUpdateWrapper<>();
        //获取当前周第一天
        String startTime = DateUtil.beginOfWeek(dateTime).toDateStr();
        //获取当前周最后一天
        String endTime = DateUtil.offsetDay(DateUtil.endOfWeek(dateTime), 1).toDateStr();
        wrapper.between(CmsCommunityLog::getCreateTime, startTime, endTime);
        wrapper.eq(CmsCommunityLog::getUserid, UserContext.getUserId());
        List<CmsCommunityLog> communityLogList = communityLogMapper.selectList(wrapper);
        Map<String, Integer> map = new HashMap<>();
        for (CmsCommunityLog communityLog : communityLogList) {
            String createTime = communityLog.getCreateTime();
            String week = DateUtil.dayOfWeekEnum(DateUtil.parseDate(createTime)).toChinese("周");
            if (map.containsKey(week)) {
                map.put(week, map.get(week) + 1);
            } else {
                map.put(week, 1);
            }
        }
        List<Object> logList = new ArrayList<>();
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            JSONObject obj = new JSONObject();
            obj.put("weekDay", entry.getKey());
            obj.put("workNum", entry.getValue() + "条");
            logList.add(obj);
        }
        return logList;
    }
}

